package flexo.graphic.entity;

import flexo.graphic.FrameListener;
import flexo.graphic.SpriteSheet;
import flexo.math.Coords;

public class Sprite extends DynamicMesh implements FrameListener
{
	protected SpriteSheet sheet;
	
	private boolean update;
	
	private boolean updateSize;
	protected float size;
	
	private String animation;
	private int nextFrame;
	private float frameTime;
	private float elapsedTime;
	private boolean reverse;
	
	public Sprite(SpriteSheet sheet)
	{
		flexo.Kernel.log("flexo.graphic.entity.Sprite", "Creating '"+sheet.getName()+"' sprite");
		this.sheet = sheet;
		sheet.grab();
		update = true;
		updateSize = true;
		frameTime = 1.0f / sheet.getFPS();
		
		// Init a 'dynamic' quad
		init(4, 6, flexo.graphic.Geometry.UPDATE_SOME);
		
		// Initialize indices
		this.setIndex(0,0);
		this.setIndex(1,1);
		this.setIndex(2,2);
		this.setIndex(3,0);
		this.setIndex(4,2);
		this.setIndex(5,3);
		
		setSize(1);
		flexo.graphic.GraphicSystem gs = (flexo.graphic.GraphicSystem)flexo.Kernel.getSystem(flexo.graphic.GraphicSystem.ID);
		gs.addFrameListener(this);
	}
	
	@ Override
	public void remove()
	{
		flexo.graphic.GraphicSystem gs = (flexo.graphic.GraphicSystem)flexo.Kernel.getSystem(flexo.graphic.GraphicSystem.ID);
		gs.removeFrameListener(this);
		sheet.remove();
		mat.remove();
		super.remove();
	}
	
	public void setSize(float size)
	{
		if (size > 0)
		{
			 this.size = size;
			 updateSize = true;
		}
	}
	
	public void setAnimation(String name)
	{
		setAnimation(name,false);
	}
	
	public void setReverse(boolean reverse)
	{
		if (this.reverse != reverse)
		{
			this.reverse = reverse;
			update = true;
		}
	}
	
	public void setAnimation(String name, boolean reverse)
	{
		if (this.animation == null || !this.animation.equals(name))
		{
			this.animation = name;
			update = true;
			elapsedTime = 0;
			nextFrame = 0;
			this.reverse = reverse;
		}
	}
	
	public void update()
	{
		if (update)
		{
			update = false;
			
			if (updateSize)
			{
				updateSize = false;
				float width = size * sheet.getAspectRatio();
				setVertexPosition(0, - width * 0.5f , size * 0.5f, 0);
				setVertexPosition(1, - width * 0.5f , -size * 0.5f, 0);
				setVertexPosition(2, width * 0.5f , -size * 0.5f, 0);
				setVertexPosition(3, width * 0.5f , size * 0.5f, 0);
			}
			
			Coords upperLeft = new Coords();
			Coords lowerRight = new Coords();
			
			nextFrame = sheet.fillTexCoords(animation, nextFrame, upperLeft, lowerRight);
			
			if (reverse)
			{
				float temp = lowerRight.x;
				lowerRight.x = upperLeft.x;
				upperLeft.x = temp;
			}
			
			setVertexTexCoord(0, upperLeft.x, upperLeft.y);
			setVertexTexCoord(1, upperLeft.x, lowerRight.y);
			setVertexTexCoord(2, lowerRight.x, lowerRight.y);
			setVertexTexCoord(3, lowerRight.x, upperLeft.y);
			
			super.update();
		}
	}

	@Override
	public void onCameraRender(){}

	@Override
	public void onFrameStart()
	{
		flexo.graphic.GraphicSystem gs = (flexo.graphic.GraphicSystem)flexo.Kernel.getSystem(flexo.graphic.GraphicSystem.ID);
		elapsedTime += gs.getElapsedTime();
		if (elapsedTime >= frameTime)
		{
			elapsedTime -= frameTime;
			update = true;
		}
	}
}
